package com.store.orm.mysql.crud.impl;

import com.store.orm.mysql.MySQLUtil;
import com.store.orm.mysql.crud.Insert;
import com.store.orm.util.MapUtil;

import java.util.*;

import static com.store.orm.common.KeyWord.*;


/**
 * @author 宫静雨
 * @version 1.0
 */
public class MySQLInsert implements Insert {
    private MySQLUtil UTIL;

    public MySQLInsert(MySQLUtil UTIL) {
        this.UTIL = UTIL;
    }

    /**
     * 为单条记录插入做准备
     */
    private Map<String, List<Object>> toResult(String tableName, Map<String, Object> map) {
        StringBuilder sb = new StringBuilder();
        sb.append(INSERT_INTO).append(tableName).append(LEFT_ROUND_BRACKET);
        Set<String> keys = map.keySet();
        keys.forEach(key -> sb.append(key).append(COMMA)); // 添加字段
        sb.deleteCharAt(sb.length() - 1).append(RIGHT_ROUND_BRACKET).append(BLANK)
                .append(VALUES).append(LEFT_ROUND_BRACKET);
        keys.forEach(key -> sb.append(QUESTION).append(COMMA)); // 添加?
        sb.deleteCharAt(sb.length() - 1).append(RIGHT_ROUND_BRACKET).append(SEMICOLON);
        List<Object> list = new ArrayList<>(map.values());
        return new MapUtil<String, List<Object>>().put(sb.toString(), list).linked();
    }

    /**
     * 为批量插入做准备, 批量插入时不可以带占位符
     */
    private String toResult2(String tableName, Map<String, Object> map) {
        StringBuilder sb = new StringBuilder();
        sb.append(INSERT_INTO).append(tableName).append(LEFT_ROUND_BRACKET);
        map.keySet().forEach(key -> sb.append(key).append(COMMA)); // 添加字段
        sb.deleteCharAt(sb.length() - 1).append(RIGHT_ROUND_BRACKET).append(BLANK)
                .append(VALUES).append(LEFT_ROUND_BRACKET);
        map.values().forEach(val -> UTIL.valInsertProcessor(sb, val));
        sb.deleteCharAt(sb.length() - 1).append(RIGHT_ROUND_BRACKET).append(SEMICOLON);
        return sb.toString();
    }

    @Override
    public <T> Map<String, List<Object>> insert(T t) {
        String tableName = UTIL.getTableName(t.getClass());
        Map<String, Object> map = UTIL.parseTToMap(t);
        return toResult(tableName, map);
    }

    @Override
    public <T> List<String> insertMany(List<T> ts) {
        if (ts.size() == 0) {
            throw new IndexOutOfBoundsException("批量插入时, 数量必须大于0");
        }
        Class<?> cls = ts.get(0).getClass();
        List<String> list = new ArrayList<>();
        ts.forEach(t -> list.add(toResult2(UTIL.getTableName(cls), UTIL.parseTToMap(t))));
        return list;
    }

    /**
     * 注意，插入时不支持时间类型的数据
     *
     * @param cls
     * @param json
     * @return
     */
    @Override
    public Map<String, List<Object>> insert(Class<?> cls, String json) {
        String tableName = UTIL.getTableName(cls);
        Map<String, Object> map = UTIL.parseJsonToMap(json);
        return toResult(tableName, map);
    }

    /**
     * 注意，插入时不支持时间类型的数据
     *
     * @param cls
     * @param jsons
     * @return
     */
    @Override
    public List<String> insertMany(Class<?> cls, List<String> jsons) {
        List<String> list = new ArrayList<>();
        jsons.forEach(json -> list.add(toResult2(UTIL.getTableName(cls), UTIL.parseJsonToMap(json))));
        return list;
    }

    @Override
    public Map<String, List<Object>> insert(Class<?> cls, LinkedHashMap<String, Object> map) {
        String tableName = UTIL.getTableName(cls);
        return toResult(tableName, map);
    }

    @Override
    public List<String> insertMany(Class<?> cls, Collection<LinkedHashMap<String, Object>> maps) {
        List<String> list = new ArrayList<>();
        maps.forEach((map -> list.add(toResult2(UTIL.getTableName(cls), map))));
        return list;
    }

    @Override
    public Map<String, List<Object>> insert(String sql, Object... args) {
        return new MapUtil<String, List<Object>>().put(sql, Arrays.asList(args)).linked();
    }

    @Override
    public List<String> insertMany(String[] sql) {
        return Arrays.asList(sql);
    }

    public MySQLUtil getUTIL() {
        return UTIL;
    }
}